<template>
  <div class="container">
    <input
      type="file"
      @change="getFile"
      multiple="multiple"
      accept=".json,.txt"
      ref="inputer"
    />
    <button class="editor-editable btn" id="editable" @click="turnEditor">
      {{ this.buttonText }}
    </button>
    <button class="editor-save btn" id="editable" @click="saveStyle">
      {{ this.saveButtonText }}
    </button>
    <div class="commandZone" id="commandZone">
      <template v-for="(com, i) in commands" v-bind:key="com">
        <img
          class="icon tool"
          :id="`${com}`"
          :title="`${commandMap[com].name}`"
          :src="images[i]"
          :name="`${com}`"
          @click="clickEvent"
        />
      </template>
      <template v-for="(com, i) in commandSelect" v-bind:key="com">
        <img
          class="icon tool"
          :id="`${com}`"
          :title="`${commandMap[com].name}`"
          :src="imagesSelect[i]"
        />
        <select
          class="tool"
          :name="`${com}`"
          :id="`${com}`"
          @change="selectChange"
        >
          <template v-for="op in commandMap[com].options" v-bind:key="op">
            <option :class="`${com}-option`" :value="`${op.value}`">
              {{ op.label }}
            </option>
          </template>
        </select>
      </template>
    </div>
    <div
      class="editor-container"
      :contenteditable="contenteditable"
      autoHeightEnabled="false"
      ref="editor"
    ></div>
  </div>
</template>

<script>
import {
  commands,
  commandSelect,
  commandMap,
  loadImage,
  execEditorCommand,
  mergeStyle,
} from "../config/Config";
const images = loadImage(commands);
const imagesSelect = loadImage(commandSelect);
const needInputUrl = ["insertImage", "createLink", "table"];

import { saveAs } from "file-saver";
export default {
  name: "HelloWorld",
  data() {
    return {
      contenteditable: false,
      buttonText: "编辑",
      commands,
      commandSelect,
      commandMap,
      images,
      imagesSelect,
      contentHtml: "",
      isTable: false,
      rowNum: 0,
      rowCount: 0,
      cellNum: 0,
      cellCount: 0,
      saveButtonText: "保存文档",
    };
  },
  props: {
    html: String,
  },
  methods: {
    turnEditor: function () {
      this.contenteditable = !this.contenteditable;
      if (this.contenteditable) {
        this.buttonText = "展示";
      } else {
        this.buttonText = "编辑";
      }
    },
    selectChange({ target }) {
      if (!this.contenteditable) {
        return;
      }
      const selection = document.getSelection();
      const { anchorNode } = selection;
      if (!anchorNode) {
        return;
      }
      if (target && target.name == "heading") {
        let html = this.$refs.editor.innerHTML;
        const { focusOffset } = selection;
        let text = html.slice(focusOffset);
        const label = target.value;
        text = `<${label}>${text}</${label}>`;
        html = html.slice(0, focusOffset);
        this.$refs.editor.innerHTML = html + text;
      } else if (target && target.name == "lineheight") {
        let html = this.$refs.editor.innerHTML;
        const { focusOffset } = selection;
        let text = html.slice(focusOffset);
        const value = target.value;
        text = `<p style="line-height:${value} !important;">${text}</p>`;
        html = html.slice(0, focusOffset);
        this.$refs.editor.innerHTML = html + text;
      } else {
        execEditorCommand(target.name, target.value);
      }
    },
    clickEvent({ target }) {
      if (!this.contenteditable) {
        return;
      }
      if (needInputUrl.includes(target.name)) {
        if (target.name === "table") {
          const value = window.prompt("请几行几列用,隔开");
          if (!value) {
            return;
          }
          const [row, col] = value.split(",").map(Number);
          this.createTable(row, col);
        } else {
          const value = window.prompt("请输入链接");
          if (!value) {
            return;
          }
          execEditorCommand(target.name, value);
        }
      } else {
        execEditorCommand(target.name);
      }
    },
    createTable(row, col) {
      const table = document.createElement("table");
      table.style =
        "width: 900px;display: table;margin: 10px 0;font-size: 20px;line-height: 2;border: 1px solid #4b4a4a !important;text-align: center;border-spacing: 0;border-collapse: collapse;";
      for (let a = 0; a < col; a++) {
        const th = document.createElement("th");
        th.style =
          "background-color: cadetblue !important;padding: 10px;border: 1px solid #4b4a4a;";
        th.innerHTML = "表头";
        table.appendChild(th);
      }
      for (let i = 0; i < row; i++) {
        const tr = document.createElement("tr");
        tr.style = "border: 0px solid #4b4a4a !important;padding: 10px;";
        for (let y = 0; y < col; y++) {
          const td = document.createElement("td");
          td.style =
            "padding: 5px;border: 1px solid #4b4a4a;word-break: break-all;";
          td.innerHTML = "表格";
          tr.appendChild(td);
        }
        table.appendChild(tr);
      }
      this.$refs.editor.appendChild(table);
    },
    getFile() {
      let inputDOM = this.$refs.inputer;
      let reader = new FileReader();
      if (!inputDOM.files[0]) {
        return;
      }
      const name = inputDOM.files[0].name;
      reader.readAsText(inputDOM.files[0]);
      reader.onload = () => {
        if (/.txt/.test(name)) {
          this.$refs.editor.innerHTML = reader.result;
        } else {
          const content = JSON.parse(reader.result);
          this.renderContent(content);
        }
      };
    },
    renderContent(contentObj) {
      const { content: contentOuter } = contentObj;
      contentOuter.forEach((item) => {
        const { type, text, content } = item;
        if (type == "paragraph") {
          this.contentHtml =
            this.contentHtml + `<p style="${mergeStyle(type)}">`;
        } else if (type == "text") {
          if (this.isTable) {
            if (this.cellNum === this.cellCount) {
              if (this.rowNum === this.rowCount) {
                this.contentHtml =
                  this.contentHtml +
                  `<span style="${mergeStyle(type)}">` +
                  text +
                  "</span></p></td></tr></table>";
                this.rowNum = 0;
                this.rowCount = 0;
                this.isTable = false;
              } else {
                this.contentHtml =
                  this.contentHtml +
                  `<span style="${mergeStyle(type)}">` +
                  text +
                  "</span></p></td></tr>";
                this.cellCount = 0;
                this.cellNum = 0;
              }
            } else {
              this.contentHtml =
                this.contentHtml +
                `<span style="${mergeStyle(type)}">` +
                text +
                "</span></p></td>";
            }
          } else {
            this.contentHtml =
              this.contentHtml +
              `<span style="${mergeStyle(type)}">` +
              text +
              "</span></p>";
          }
        } else if (type == "table") {
          this.contentHtml =
            this.contentHtml + `<table style="${mergeStyle(type)}">`;
          this.isTable = true;
          this.rowCount = content.length;
        } else if (type == "row") {
          this.contentHtml =
            this.contentHtml + `<tr style="${mergeStyle(type)}">`;
          this.cellCount = content.length;
          ++this.rowNum;
        } else if (type == "cell") {
          this.contentHtml =
            this.contentHtml + `<td style="${mergeStyle(type)}">`;
          ++this.cellNum;
        }
        item.content && this.renderContent(item);
      });
      this.$refs.editor.innerHTML = this.contentHtml.trim();
    },
    saveStyle() {
      let data = new Blob([this.$refs.editor.innerHTML], {
        type: "text/plain;chaerset=utf-8",
      });
      saveAs(data, "样式和内容.txt");
    },
  },
  created() {},
  mounted() {},
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.container {
  max-width: 1000px;
  margin: 0 auto;
  position: relative;
  word-break: break-all;
  white-space: pre-wrap;
  white-space: -moz-pre-wrap;
  white-space: -pre-wrap;
  white-space: -o-pre-wrap;
  word-wrap: break-word;
}
.commandZone {
  margin: 50px 0;
  border: 1px solid #aaa;
  padding: 10px;
  padding-bottom: 0;
  display: flex;
  flex-wrap: wrap;
  overflow: hidden;
  text-align: center;
}
.editor-container {
  border: 1px solid #ccc;
  padding: 15px;
  outline: none;
  line-height: 1.8;
  max-height: 500px;
  overflow-y: auto;
  text-align: left;
}
.editor-container:focus {
  border: 1px solid #999;
}
.btn {
  color: black;
  padding: 0 5px;
  display: block;
  cursor: pointer;
  font-size: 12px;
  height: 21px;
}
.icon {
  cursor: pointer;
  width: 30px;
  height: 30px;
}
.icon:hover {
  color: #000;
}
.tool {
  margin-right: 10px;
  margin-bottom: 10px;
}
select {
  width: 60px;
  height: 21px;
}
.editor-editable {
  position: absolute;
  right: 0;
  top: -50px;
  cursor: pointer;
}
.editor-save {
  position: absolute;
  right: 0;
  top: -20px;
  cursor: pointer;
}
.createtable {
  width: 900px;
  display: table;
  margin: 10px 0;
  font-size: 20px;
  line-height: 2;
  border: 1px solid #4b4a4a !important;
  text-align: center;
  border-spacing: 0;
  border-collapse: collapse;
}
.createth {
  background-color: cadetblue !important;
  padding: 10px;
}
.createtr {
  padding: 10px;
}
.createtd {
  padding: 5px;
  border: 1px solid #4b4a4a;
  word-break: break-all;
}
</style>
